package cn.slg.module.system.dal.dataobject.state;

import cn.slg.module.system.dal.dataobject.wujiang.WuJiangDO;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.Method;
import java.util.List;

import static cn.slg.module.system.service.pk.utils.DieAndRescue.rescue;
import static cn.slg.module.system.service.pk.utils.Harm.skillHarmCount;
import static cn.slg.module.system.service.pk.utils.Show.*;

@Data
@NoArgsConstructor
// 持续性状态
// 每回合武将开始行动时触发
// 同种状态不可叠加，但可以刷新（只要状态名相同，无论是否来自同一个战法，都只能刷新）
public class PersistenceState extends State {

    private boolean canAdd = false;

    // 同种状态，无论是否来自哪个战法，都只能刷新，不能叠加
    private boolean canRefresh = true;

    // 该状态的技能面板伤害率或治疗率(还没有受到智力或武力的影响)
    private Float baseRate;

    // 是不是溃逃状态，因为比较特殊，所以单独设定
    private boolean isRun = false;

    // 该状态是否受到属性影响
    private boolean isAffectedByPv;


    // 来自同一战法的同种属性状态将会刷新持续回合。
    public void refresh(WuJiangDO inflictor, WuJiangDO receiver, byte continueTimes) {
        this.setInflictor(inflictor);  // 刷新施加者
        this.setRemainTimes(continueTimes);    // 刷新持续时间
        // [被施加者]的[状态名]效果已刷新
        System.out.println(spacing2() + showName(receiver) + "的" + parcel1(stateName) + "状态已刷新" + parcel2(continueTimes));
    }


    public void begin() {
        // 接收者挂上这个状态
        receiver.getPersistenceStates().add(this);
        // [被施加者]被[施加者]的【技能名】施加了【状态名】(持续时间)
        System.out.println(spacing2() + showName(receiver) + "被" + showName(inflictor) + "的" + parcel1(skillName) + "施加了" + parcel1(stateName) + parcel2(continueTimes));
    }

    // 持续性状态有两类：
    // 1.造成治疗效果（急救：受到伤害时恢复兵力；休整：行动时恢复兵力）
    // 2.造成伤害（叛逃：按照施放者智力或武力更高一项计算伤害。灼烧、水攻、中毒、溃逃、沙暴（按照施放者智力计算上海））
    // 考虑到叛逃效果是基于武力或智力更高的一项，需要 isPhysical
    // 考虑到有些技能施加的状态受到施加者属性的影响，有些不受属性的影响，需要 isAffectedByPv
    // 除了叛逃，其他都是按照智力算的
    public boolean effect() {
        boolean isEnd = false;
        // 【被施加者】执行来自[技能名]的[状态名]效果
        System.out.println(spacing2() + showName(receiver) + "执行来自" + parcel1(skillName) + "的" + parcel1(stateName) + "效果");

        // TODO 持续性状态会被净化吗？以后考虑
        if (skillName.equals("急救") || skillName.equals("休整")) {
            // 恢复兵力
            rescue(isAffectedByPv, inflictor, receiver, baseRate, skillName);

        } else {
            // 造成伤害
            Short harm = 0;
            if (isRun) {
                // 如果是溃逃，必定受到属性影响
                if (inflictor.getPvWuLi() > inflictor.getPvZhiLi()) {
                    // 如果施加者武力更高
                    float harmRate = baseRate * isAffectedByPv(inflictor.getPvWuLi());
                    harm = inflictor.whenCalculateHarm(true, inflictor, receiver, inflictor::getPvWuLi, receiver::getPvTongShuai, harmRate);
                } else {
                    // 如果施加者智力更高
                    float harmRate = baseRate * isAffectedByPv(inflictor.getPvZhiLi());
                    harm = inflictor.whenCalculateHarm(false, inflictor, receiver, inflictor::getPvZhiLi, receiver::getPvZhiLi, harmRate);
                }
            } else {
                // 如果不是溃逃效果
                float harmRate;
                if (isAffectedByPv) {
                    // 如果状态效果受到属性影响，（只受到智力影响）
                    harmRate = baseRate * isAffectedByPv(inflictor.getPvZhiLi());
                } else {
                    // 如果状态不受属性影响，即战法面板伤害率
                    harmRate = baseRate;
                }
                harm = inflictor.whenCalculateHarm(false, inflictor, receiver, inflictor::getPvZhiLi, receiver::getPvZhiLi, harmRate);
            }

            // 累计 攻击者 战法杀伤(上面已经计算好此次攻击的伤害值了，无论目标死没死，这都要先统计)
            skillHarmCount(inflictor, skillName, harm);

            // 先处理受攻击者(返回是否战斗结束)
            isEnd = receiver.whenIsStateAttack(inflictor, skillName, stateName, harm);

            // 战斗是否结束了
            if (!isEnd) {
                // TODO 该状态被触发后，施加者和被施加者会触发什么
            }

        }

        return isEnd;
    }

    // 移除该持续性状态
    public void end() {
        receiver.getPersistenceStates().remove(this);
    }

    public PersistenceState(boolean isNegative, boolean isRun, boolean isAffectedByPv, String stateName, WuJiangDO inflictor, WuJiangDO receivers, Method skill, String skillName, byte continueTimes, Float baseRate) {
        super(isNegative, stateName, inflictor, receivers, skill, skillName, continueTimes);
        this.baseRate = baseRate;
        this.isRun = isRun;
        this.isAffectedByPv = isAffectedByPv;
    }

    public static boolean canAddState(String stateName, WuJiangDO inflictor, WuJiangDO receiver, String skillName, byte continueTimes) {
        // TODO 目标身上有什么状态，能阻止持续性状态吗？

        // 首先看能否叠加。即武将身上是否已经有相同战法施加的这一相同状态，
        List<PersistenceState> persistenceStates = receiver.getPersistenceStates();

        boolean canAdd = true;      // 默认能够将该属性状态添加到接收者身上

        // 遍历接收者身上的所有 属性状态
        for (PersistenceState persistenceState : persistenceStates) {
            // 如果状态名相同
            if (stateName.equals(persistenceState.getStateName())) {
                canAdd = false;
                // TODO 虽然不能叠加，但是能够刷新，这里进行刷新。
                if (persistenceState.canRefresh) {
                    WuJiangDO inflictor1 = persistenceState.getInflictor();
                    System.out.println(spacing2() + showName(receiver) + "已有来自" + showName(inflictor1) + parcel1(skillName) + "的" + parcel1(stateName) + "效果，无法叠加");

                    // 可以刷新已有的状态
                    persistenceState.refresh(inflictor, receiver, continueTimes);
                }
            }
        }
        return canAdd;
    }

    /**
     *
     * @param isNegative    是不是负面状态
     * @param isRun         是不是溃逃状态
     * @param isAffectedByPv 是不是受到属性值影响
     * @param stateName     状态名
     * @param inflictor     状态施加者
     * @param receiver      状态接收者
     * @param skill         施加状态的技能
     * @param skillName     施加状态的技能名
     * @param continueTimes 状态持续事件
     * @param baseRate      状态效果面板百分比
     */
    public static void addState(boolean isNegative, boolean isRun, boolean isAffectedByPv, String stateName, WuJiangDO inflictor, WuJiangDO receiver, Method skill, String skillName, byte continueTimes, Float baseRate) {
        // TODO 能够添加，就施加到武将身上
        PersistenceState persistenceState = new PersistenceState(isNegative, isRun, isAffectedByPv, stateName, inflictor, receiver, skill, skillName, continueTimes, baseRate);
        // TODO 生效 [被施加者]的[状态名]效果已刷新
        persistenceState.begin();
    }
}
